//
//  NetworkTools.swift
//  测试-05-AFN的封装
//
//  Created by Leon on 15/10/16.
//  Copyright © 2015年 Leon. All rights reserved.
//

import UIKit
import AFNetworking
// 引入是传框架 文件夹得名字

 /// HTTP访问方法
enum HTTPRequestMethod: String {
    case GET = "GET"
    case POST = "POST"
}

// MARK: 网络工具
class NetworkTools: AFHTTPSessionManager {
    
    // MARK: - 应用程序信息
    private let AppKey: String = "1649135838"
    private let AppSecret: String = "69916968f5d9109758a39ac0c033a40c"
    private let redirect_uri: String = "http://www.baidu.com"
    
    /// 网络请求完成回调，类似于 OC 的 typeDefine
    typealias LZFRequestCallBack = (result: AnyObject?, error: NSError?)->()
    
    // 工具：首先当然来个单例
    static let shareTools:NetworkTools = {
    
        let tools = NetworkTools(baseURL: nil)
        
        // 插入解析类型
        tools.responseSerializer.acceptableContentTypes?.insert("text/plain")
        
        return tools
    }()
    

}

// // MARK: - 发送微博的方法
extension NetworkTools {
    
    ///  发送微博
    ///
    ///  - parameter status:   微博内容
    ///  - parameter finished: 完成回调
    func sendStatus(status: String, image: UIImage?, finished: LZFRequestCallBack) {
        
        var parameters = [String: AnyObject]()
        
        parameters["status"] = status
        
        if image == nil {
            
            let urlString = "https://api.weibo.com/2/statuses/update.json"
            tokenRequest(.POST, URLString: urlString, parameters: parameters, finished: finished)
            
        } else {
            
            let data = UIImagePNGRepresentation(image!)
            let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
            upload(urlString, parameters: parameters, data: data!, name: "pic", finished: finished)
            
        }
        
        
    }
    
}

// MARK: - 微博主页的方法
extension NetworkTools {
    
//    since_id	若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0。
//    max_id    若指定此参数，则返回ID小于或等于max_id的微博，默认为0。
    
    func loadStatus(since_id since_id: Int, max_id: Int, finished:LZFRequestCallBack) {
        
        var parameters = [String: AnyObject]()
        // 判断 上拉/下拉
        if since_id > 0 {
            parameters["since_id"] = since_id
        } else if max_id > 0 {
            parameters["max_id"] = max_id - 1 
        }
        
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        tokenRequest(.GET, URLString: urlString, parameters: parameters, finished: finished)
        
    }
}

// MARK: - 用户信息相关方法
extension NetworkTools {
    /**
    获取用户信息
    
    - parameter uid:          需要查询的用户ID。
    - parameter finished:     回调
    */
    func loadUserInfo(uid:String, finished:LZFRequestCallBack) {

        
        var parameters = [String: AnyObject]()
        let urlString = "https://api.weibo.com/2/users/show.json"
        
        parameters["uid"] = uid
        
        tokenRequest(.GET, URLString: urlString, parameters: parameters, finished: finished)
        
    }
}


// MARK: - OAuth相关方法
extension NetworkTools {
    /// OAuth 授权 URL
    /// - see: [http://open.weibo.com/wiki/Oauth2/authorize](http://open.weibo.com/wiki/Oauth2/authorize)
    var OAuthURL: NSURL {
        
        let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(AppKey)&redirect_uri=\(redirect_uri)"
        
        return NSURL(string: urlString)!
    }
    
    /// 加载 AccessToken
    func loadAccessToken(code: String, finished: LZFRequestCallBack) {
        
        let urlString = "https://api.weibo.com/oauth2/access_token"
        
        let parameters = ["client_id":AppKey,
                        "client_secret":AppSecret,
                        "grant_type":"authorization_code",
                        "code":code,
                        "redirect_uri":redirect_uri]
        
        request(.POST, URLString: urlString, parameters: parameters, finished:finished)
    }
   
}

// MARK: - 封装AFN网络方法
extension NetworkTools {
    
    /// 向 parameters 字典中追加 token 参数
    ///
    /// - parameter parameters: 参数字典
    ///
    /// - returns: 是否追加成功
    /// - 默认情况下，关于函数参数，在调用时，会做一次 copy，函数内部修改参数值，不会影响到外部的数值
    /// - inout 关键字，相当于在 OC 中传递对象的地址
    func appendToken(inout parameters: [String:AnyObject]?) -> Bool {
        
        guard let token = UserAccountViewModel.shareAccount.accessToken else {
            return false
        }
        
        // 2 判断parameters 是否有值
        if parameters == nil {
            parameters = [String: AnyObject]()
        }
        
        // 3 添加token值
        parameters!["access_token"] = token
        return true
    }
    
    ///  使用token发送网络请求
    ///
    ///  - parameter method:     GET/POST
    ///  - parameter URLString:  URLString
    ///  - parameter parameters: 参数字典
    ///  - parameter finished:   完成回调
    func tokenRequest(method:HTTPRequestMethod, URLString: String, var parameters: [String:AnyObject]?, finished:LZFRequestCallBack) {
        
        // 0 判断是否登录，以及拼接token
        if !appendToken(&parameters) {
            
            // 如果 token 为 nil，完成回调，告诉调用者为空
            finished(result: nil, error: NSError(domain: "cn.leon.error", code: -1001, userInfo: ["message":"token is nil"]))
            return
        }
        
        // 1 发送请求
        request(method, URLString: URLString, parameters: parameters, finished: finished)
        
    }
    
    /**
    网络请求
    
    - parameter method:     GET/POST
    - parameter URLString:  URLString
    - parameter parameters: 参数字典
    - parameter finished:   完成回调
    */
    
    func request(method:HTTPRequestMethod, URLString: String, parameters: [String:AnyObject]?, finished:LZFRequestCallBack) {
        
        // 定义成功回调
        let success = {(task:NSURLSessionDataTask, result:AnyObject) -> Void in
            finished(result: result, error: nil)
        }
        
        // 定义失败回调
        let failure = {(task:NSURLSessionDataTask, error:NSError) -> Void in
            finished(result: nil, error: error)
            print(error)
        }
        
        if method == HTTPRequestMethod.GET {
            GET(URLString, parameters: parameters, success: success, failure: failure)
        } else {
            POST(URLString, parameters: parameters, success: success, failure: failure)
        }

        
    }
    
    ///  上传文件
    func upload(URLString: String, var parameters: [String:AnyObject]?, data: NSData, name: String, finished:LZFRequestCallBack) {
        
        // 0 判断是否登录，以及拼接token
        if !appendToken(&parameters) {
            
            // 如果 token 为 nil，完成回调，告诉调用者为空
            finished(result: nil, error: NSError(domain: "cn.leon.error", code: -1001, userInfo: ["message":"token is nil"]))
            return
        }
        
        POST(URLString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
            
            formData.appendPartWithFileData(data, name: name, fileName: "xxx", mimeType: "application/octet-stream")
            }, success: { (_, result) -> Void in
                finished(result: result, error: nil)
            }) { (_, error) -> Void in
                finished(result: nil, error: error)
        }
    }
    /**
    1. data 要上传文件的二进制数据
    2. name 是服务器定义的字段名称 － 后台接口文档会提示
    3. fileName 是保存在服务器的文件名，但是：现在通常可以`乱写`，后台会做后续的处理
    - 根据上传的文件，生成 缩略图，中等图，高清图
    - 保存在不同路径，并且自动生成文件名
    
    - fileName 是 HTTP 协议定义的属性
    4. mimeType / contentType: 客户端告诉服务器，二进制数据的准确类型
    - 大类型/小类型
    * image/jpg image/gif image/png
    * text/plain text/html
    * application/json
    - 无需记忆
    - 如果不想告诉服务器准确的类型
    * application/octet-stream
    */
    
    
}
